use linfa::{
    prelude::SingleTargetRegression,
};
use ndarray::prelude::*;
use plotters::prelude::*;

fn main() {
    // simple_vec();
    metrics();
}

fn simple() {
    let x = array![1., 2., 3., 4., 5.];
    let y = array![1., 3., 2., 3., 5.];
    let root =
        SVGBackend::new("./examples/LinearRegression/simple.svg", (640, 480)).into_drawing_area();
    root.fill(&WHITE).unwrap();

    let mut chart = ChartBuilder::on(&root)
        .x_label_area_size(40)
        .y_label_area_size(40)
        .build_cartesian_2d(0.0..6.0f64, 0.0..6.0f64)
        .unwrap();
    chart
        .configure_mesh()
        .disable_x_mesh()
        .disable_y_mesh()
        .draw()
        .unwrap();
    chart
        .draw_series(
            x.iter()
                .zip(y.iter())
                .map(|(x, y)| Circle::new((*x, *y), 5, RED.mix(0.3).filled())),
        )
        .unwrap();

    let x_mean = x.mean().unwrap();
    let y_mean = y.mean().unwrap();
    let mut num = 0.0;
    let mut d = 0.0;
    for (x_i, y_i) in x.iter().zip(y.iter()) {
        num += (x_i - x_mean) * (y_i - y_mean);
        d += (x_i - x_mean).powi(2);
    }
    let a = num / d;
    let b = y_mean - a * x_mean;
    println!("{}, {}", a, b);
    chart
        .draw_series(LineSeries::new(
            x.iter().zip(y.iter()).map(|(x, _y)| (*x, a * *x + b)),
            BLUE.filled(),
        ))
        .unwrap();
    println!("{}", a * 6.0 + b);
}

// 向量化运算带来巨大的提升
fn simple_vec() {
    let x = array![1., 2., 3., 4., 5.];
    let y = array![1., 3., 2., 3., 5.];
    let x_mean = x.mean().unwrap();
    let y_mean = y.mean().unwrap();
    let num = (&x - x_mean).dot(&(&y - y_mean));
    let d = (&x - x_mean).dot(&(&x - x_mean));
    let a = num / d;
    let b = y_mean - a * x_mean;
    println!("{}, {}", a, b);
}

fn metrics() {
    let array1 = array![1.2, 2.3];
    let ret = array1.mean_squared_error(&array![1.2, 2.3]);
    let c: f64 = 3.4;
    println!("{}", c.sqrt());
    println!("ret: {}", (ret.unwrap() as f64).sqrt());
    println!("r2: {}", array1.r2(&array![1.2, 2.3]).unwrap());
    let array2 = array![[1.0, 2.0, 3.0], [5.0, 5.0, 6.0], [8.0, 8.0, 9.0]];
    println!("{}", array2);
    

    //println!("{:?}", array2.inv());

    let a = array![[1.0, 2.0], [3.0, 4.0]];
    let b = array![[3.0, 4.0]];
    println!("{}", a.dot(&b.t()));
}

// 多远线性回归的问题
